﻿using DotNetty.Buffers;
using DotNetty.Codecs.Http;
using DotNetty.Common.Utilities;
using JGSY.DotNetty.Common;
using JGSY.DotNetty.Server.Core;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace JGSY.DotNetty.Server.CoreImpl
{
    /// <summary>
    /// HTTP请求处理器的具体实现类
    /// 实现了IHttpHandler接口，用于处理HTTP请求并生成响应
    /// </summary>
    public class HttpHandlerImpl : IHttpHandler
    {
        /// <summary>
        /// 处理HTTP请求并返回响应
        /// </summary>
        /// <param name="request">完整的HTTP请求对象</param>
        /// <returns>生成的HTTP响应对象</returns>
        public async Task<IFullHttpResponse> GetHttpResponseAsync(IFullHttpRequest request)
        {
            // 检查请求处理结果是否成功
            if (!request.Result.IsSuccess)
            {
                // 如果请求处理失败，返回400 Bad Request响应
                return GetHttpResponse(HttpResponseStatus.BadRequest);
            } 
            return await GetFileResponseAsync(request);
        }


        #region 私有方法

        /// <summary>
        /// 获得文件Byte数组
        /// </summary>
        /// <param name="filePath"></param>
        /// <returns></returns>
        private async Task<byte[]> GetFileBytesAsync(string filePath)
        {
            if (!File.Exists(filePath)) throw new DotNettyServerException("文件不存在");
            byte[] result = await File.ReadAllBytesAsync(filePath);
            return result;
        }
        /// <summary>
        /// 获得文件返回
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        private async Task<IFullHttpResponse> GetFileResponseAsync(IFullHttpRequest request)
        {
            string url = request.Uri == "/" ? "/Index.html" : request.Uri;
            string filePath = $"{AppDomain.CurrentDomain.BaseDirectory}HtmlPages{url}";
            string extension = Path.GetExtension(filePath);
            if (string.IsNullOrEmpty(extension)) return GetHttpResponse(HttpResponseStatus.NotFound);
            if (!File.Exists(filePath)) return GetHttpResponse(HttpResponseStatus.NotFound);
            byte[] body = await GetFileBytesAsync(filePath);
            string contentType = MimeManager.GetContentType(extension);
            Dictionary<AsciiString, object> headers = GetDefaultHeaders(contentType);
            return GetHttpResponse(HttpResponseStatus.OK, body, headers);
        }





        /// <summary>
        /// 根据状态码获取HTTP响应
        /// 使用默认的响应头，不包含响应体
        /// </summary>
        /// <param name="status">HTTP响应状态码</param>
        /// <returns>生成的HTTP响应对象</returns>
        private IFullHttpResponse GetHttpResponse(HttpResponseStatus status)
        {
            // 获取默认响应头
            Dictionary<AsciiString, object> headers = GetDefaultHeaders();
            // 调用重载方法生成响应
            return GetHttpResponse(status, headers);
        }

        /// <summary>
        /// 根据状态码和字符串响应体获取HTTP响应
        /// 使用指定的文本类型响应头
        /// </summary>
        /// <param name="status">HTTP响应状态码</param>
        /// <param name="body">字符串类型的响应体内容</param>
        /// <returns>生成的HTTP响应对象</returns>
        private IFullHttpResponse GetHttpResponse(HttpResponseStatus status, string body)
        {
            // 验证输入参数
            if (body == null)
                throw new ArgumentNullException(nameof(body));

            // 获取默认响应头，指定内容类型为纯文本UTF-8编码
            Dictionary<AsciiString, object> headers = GetDefaultHeaders("text/plain;charset=UTF-8");
            // 调用重载方法生成响应
            return GetHttpResponse(status, body, headers);
        }

        /// <summary>
        /// 根据状态码和字节数组响应体获取HTTP响应
        /// 使用二进制流类型响应头
        /// </summary>
        /// <param name="status">HTTP响应状态码</param>
        /// <param name="body">字节数组类型的响应体内容</param>
        /// <returns>生成的HTTP响应对象</returns>
        private IFullHttpResponse GetHttpResponse(HttpResponseStatus status, byte[] body)
        {
            // 验证输入参数
            if (body == null)
                throw new ArgumentNullException(nameof(body));

            // 获取默认响应头，指定内容类型为二进制流
            Dictionary<AsciiString, object> headers = GetDefaultHeaders("application/octet-stream");
            // 调用重载方法生成响应
            return GetHttpResponse(status, body, headers);
        }

        /// <summary>
        /// 根据状态码和响应头获取HTTP响应
        /// 不包含响应体
        /// </summary>
        /// <param name="status">HTTP响应状态码</param>
        /// <param name="headers">响应头字典</param>
        /// <returns>生成的HTTP响应对象</returns>
        private IFullHttpResponse GetHttpResponse(HttpResponseStatus status, Dictionary<AsciiString, object> headers)
        {
            // 验证输入参数
            if (headers == null)
                throw new ArgumentNullException(nameof(headers));

            // 调用重载方法生成响应，使用空字符串作为响应体
            return GetHttpResponse(status, string.Empty, headers);
        }

        /// <summary>
        /// 根据状态码、字符串响应体和响应头获取HTTP响应
        /// 将字符串转换为字节数组后处理
        /// </summary>
        /// <param name="status">HTTP响应状态码</param>
        /// <param name="body">字符串类型的响应体内容</param>
        /// <param name="headers">响应头字典</param>
        /// <returns>生成的HTTP响应对象</returns>
        private IFullHttpResponse GetHttpResponse(HttpResponseStatus status, string body, Dictionary<AsciiString, object> headers)
        {
            // 验证输入参数
            if (body == null)
                throw new ArgumentNullException(nameof(body));
            if (headers == null)
                throw new ArgumentNullException(nameof(headers));

            // 将字符串转换为UTF-8编码的字节数组
            // 如果字符串为空，则使用空字节数组
            byte[] bodyData = string.IsNullOrEmpty(body) ? Array.Empty<byte>() : Encoding.UTF8.GetBytes(body);
            // 调用重载方法生成响应
            return GetHttpResponse(status, bodyData, headers);
        }

        /// <summary>
        /// 核心方法：根据状态码、字节数组响应体和响应头生成最终的HTTP响应
        /// 这是所有重载方法的最终实现
        /// </summary>
        /// <param name="status">HTTP响应状态码</param>
        /// <param name="body">字节数组类型的响应体内容</param>
        /// <param name="headers">响应头字典</param>
        /// <returns>生成的HTTP响应对象</returns>
        private IFullHttpResponse GetHttpResponse(HttpResponseStatus status, byte[] body, Dictionary<AsciiString, object> headers)
        {
            // 验证输入参数
            if (status == null)
                throw new ArgumentNullException(nameof(status));
            if (headers == null)
                throw new ArgumentNullException(nameof(headers));

            DefaultFullHttpResponse result;

            // 检查响应体是否存在
            if (body != null && body.Length > 0)
            {
                // 将字节数组包装为Netty的ByteBuffer
                IByteBuffer bodyBuffer = Unpooled.WrappedBuffer(body);
                // 创建包含响应体的HTTP响应对象，使用HTTP/1.1版本
                result = new DefaultFullHttpResponse(HttpVersion.Http11, status, bodyBuffer);

                // 设置Content-Length响应头
                result.Headers.Set(HttpHeaderNames.ContentLength, body.Length);
            }
            else
            {
                // 创建不包含响应体的HTTP响应对象，使用HTTP/1.1版本
                result = new DefaultFullHttpResponse(HttpVersion.Http11, status);
            }

            // 将所有响应头添加到响应对象中
            foreach ((AsciiString key, object value) in headers)
            {
                // 跳过已由系统自动设置的Content-Length头
                if (key.Equals(HttpHeaderNames.ContentLength))
                    continue;

                result.Headers.Set(key, value);
            }

            // 返回生成的响应对象
            return result;
        }

        /// <summary>
        /// 获取默认的HTTP响应头集合
        /// 包含服务器信息、日期等标准响应头
        /// </summary>
        /// <param name="contentType">内容类型，可为null</param>
        /// <returns>包含默认响应头的字典</returns>
        private Dictionary<AsciiString, object> GetDefaultHeaders(string contentType = null)
        {
            // 创建响应头字典并初始化默认值
            var headers = new Dictionary<AsciiString, object>
        {
            // 设置响应日期为当前UTC时间（符合HTTP标准）
            { HttpHeaderNames.Date, DateTime.UtcNow },
            // 设置服务器标识
            { HttpHeaderNames.Server, "MateralDotNettyServer" },
            // 设置默认接受的语言
            { HttpHeaderNames.AcceptLanguage, "zh-CN,zh;q=0.9" }
        };

            // 如果指定了内容类型，则添加到响应头中
            if (!string.IsNullOrEmpty(contentType))
            {
                headers[HttpHeaderNames.ContentType] = contentType;
            }

            return headers;
        }

      

  



        #endregion
    }
}